﻿using System.Windows;
using System.Windows.Input;
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections.ObjectModel;
//using Gma.UserActivityMonitor;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Threading;
using System.Windows.Threading;

namespace MercuryFE
{
    public partial class CoverFlow : MyWindow
    {
        ProcessHandler _processHandler = null;
        private MenuLevel _currentMenu = null;
        private Dictionary<int, int> _levelSelection;

        private static string _processErrorMessage = "";
        private bool _confirmedExit = false;

        public delegate void ShowErrorMessageDelegate();

        private ShowErrorMessageDelegate showError;

        public CoverFlow()
        {
            InitializeComponent();

            _levelSelection = new Dictionary<int, int>();

            showError = new ShowErrorMessageDelegate(ShowErrorMessage);

            _processHandler = new ProcessHandler(this);
            _processHandler.ProcessComplete += new ProcessHandler.ProcessCompletedHandler(_processHandler_ProcessComplete);

            App.__navigationHook.CurrentNavigationType = NavigationHook.NavigationType.Standard;

            getMenuLevel(0);

       }

        public override void DoNavigation(NavigationHook.NavigationTask navigationTask, bool normalSpeed)
        {
            int maxIndex = _currentMenu.Links.Count - 1;
            int minIndex = 0;
            bool indexChange = false;

            switch (navigationTask)
            {
                case NavigationHook.NavigationTask.Left:
                    if (flow.SelectedIndex > minIndex)
                        flow.SelectedIndex--;
                    else
                        flow.SelectedIndex = maxIndex;

                    indexChange = true;
                    break;
                case NavigationHook.NavigationTask.Right:
                    if (flow.SelectedIndex == maxIndex)
                        flow.SelectedIndex = minIndex;
                    else
                        flow.SelectedIndex++;

                    indexChange = true;
                    break;
                case NavigationHook.NavigationTask.Up:

                    break;
                case NavigationHook.NavigationTask.Down:

                    break;
                case NavigationHook.NavigationTask.Select:
                    this.handleLink();
                    break;
                case NavigationHook.NavigationTask.Back:
                    if (_currentMenu.Level != 0) //_currentLevel != 0)
                        getMenuLevel(_currentMenu.ParentMenuId);
                    else if (_confirmedExit == false)
                    {
                        showExitConfirmation();
                        _confirmedExit = true;
                    }
                    else
                    {
                        exitProgram();
                    }

                    break;
                case NavigationHook.NavigationTask.Pause:
                    this.showGameDetails();
                    break;

            }
            if (indexChange)
            {
                flow_IndexUpdated();
            }
        }

        void flow_IndexUpdated()
        {
            // called when a new selection is made - updates all the text/ icons on the interface nicely..
            string textValue = "";
            string menuPath = "";

            bool bShowPlayStats = false;
            bool bShowNumPlayers = false;

            spNPlayers.Children.Clear();
            spEmulatorImage.Children.Clear();


            // if we have links for this menu path - try and get the value..
            if (_currentMenu.Links.Count > 0 && flow.SelectedIndex >= 0)
            {
                int currentIndex = flow.SelectedIndex;
                if (currentIndex < _currentMenu.Links.Count)
                {
                    MenuLink currentItem = _currentMenu.Links[currentIndex];
                    // text along bottom (title)
                    textValue = currentItem.Name.ToString();
                    if (currentItem.IsMenu)
                        textValue = "[ " + textValue + " ]";
                    else
                    {
                        // a game...

                        // played stats
                        bShowPlayStats = true;
                        tbLastPlayed.Text = currentItem.LastPlayed == null ? "Never" : ((DateTime)currentItem.LastPlayed).ToLongDateString();
                        tbNumberPlayed.Text = currentItem.NumberTimesPlayed==null?"Never":currentItem.NumberTimesPlayed.ToString();
                        tbTotalPlayed.Text = currentItem.TotalTimePlayed == null ? "Never" : currentItem.TotalTimePlayed.ToString() + " mins";
                        

                        // always show emulator image (or attempt anyway)
                        spEmulatorImage.Children.Add(ClientLib.getImage(currentItem.EmulatorImage));


                        // other stuff is mame specific
                        if (currentItem.IsMame)
                        {
                            spNPlayers.Children.Add(ClientLib.generateNPlayersImage(currentItem.NPlayers));
                            bShowNumPlayers = true;

                        }

                    }

                    
                } 
                
            }

            menuPath = string.Join(" - ", _currentMenu.MenuPath.ToArray());

            tbTitle.Text = textValue;
            tbPathCrumb.Text = menuPath;


            ClientLib.showHideElement(bShowPlayStats, bPlayStats);
            ClientLib.showHideElement(bShowNumPlayers, gNumPlayers);



        }

        public void getMenuLevel(int menuId) 
        {

            _currentMenu = ClientLib.getMenuLevel(menuId, false);

            // find the right index to select (since we remember last time we visited the level)
            int selectedIndex = 0;
            if (_levelSelection.ContainsKey(_currentMenu.Level))
            {
                int prevSelection = _levelSelection[_currentMenu.Level];
                // check if key in links
                for (int i = 0; i < _currentMenu.Links.Count; i++)
                {
                    MenuLink link = _currentMenu.Links[i];
                    if (link.Key == prevSelection && link.IsMenu)
                    {
                        selectedIndex = i;
                        break;
                    }
                }
            }
            
            flow.ItemsSource = _currentMenu.Links;
            flow.SelectedIndex = selectedIndex;
            flow_IndexUpdated();         

        }

        public void launchGame(int gameId)
        {
            string error = "";
            string commandline = "";

            App.__navigationHook.setGameKeyMappings(gameId);

            bool success = _processHandler.LaunchGame(gameId, ref error, ref commandline);

            if (!success)
            {
                _processErrorMessage = _processHandler.ErrorMessage;
                showError();
            }

        }

        private void showExitConfirmation()
        {
            message.Text = "Are you sure you want to leave?" + Environment.NewLine + Environment.NewLine
                + "Press 'Back' again to confirm.";
            message.Visibility = System.Windows.Visibility.Visible;
        }

        private void exitProgram()
        {
            // initiate exit sequence
            ClientLib.exitProgram();
        }

        // delegate
        public void ShowErrorMessage()
        {
            //ClientLib.showErrorMessage(_processErrorMessage, this);
            message.Text = _processErrorMessage;
            message.Visibility = System.Windows.Visibility.Visible;
        }

        void _processHandler_ProcessComplete(string ErrorMessage)
        {
            if (ErrorMessage != "")
            {
                _processErrorMessage = ErrorMessage;

                this.Dispatcher.Invoke(DispatcherPriority.Normal, showError);
            }

        }

        private void handleLink()
        {
            int index = flow.SelectedIndex;

            MenuLink link = _currentMenu.Links[index];

            if (link.IsMenu)
            {
                if (_levelSelection.ContainsKey(_currentMenu.Level)) //_currentLevel))
                    _levelSelection[_currentMenu.Level] = link.Key; //_currentLevel
                else
                    _levelSelection.Add(_currentMenu.Level, link.Key); //_currentLevel

                getMenuLevel(link.Key); //, 0);
            }
            else
                launchGame(link.Key);

        }

        private void showGameDetails()
        {
            int index = flow.SelectedIndex;

            MenuLink link = _currentMenu.Links[index];

            if (!link.IsMenu)
            {
                GameDetails gd = new GameDetails(link.Key);
                gd.Width = this.ActualWidth;
                gd.Height = this.ActualHeight;
                gd.Owner = this;
                gd.ShowDialog();
            }

        }

        private void flow_LayoutUpdated(object sender, EventArgs e)
        {
            flow_IndexUpdated();
        }


    }
}
